package org

import (
	"d-serv-go/server/core/bean"
	"d-serv-go/server/core/cache"
	"d-serv-go/server/core/consts"
	"d-serv-go/server/core/db"
	"d-serv-go/server/core/log"
	"d-serv-go/server/core/util"
	strutils "d-serv-go/server/core/util/stringutils"
	"strings"
)

var AclMgr = NewAclMgr()

type aclMgr struct {
}

func NewAclMgr() *aclMgr {
	return &aclMgr{}
}

func (a *aclMgr) GetDictAcls(dictId, userCode string) []string {
	if acls, ok := cache.CacheMgr.Get(userCode, consts.CACHE_DICT_ACL_PRE_CMPY+dictId).(string); !ok {
		userBean, _ := db.UserMgr.GetUser(userCode)
		sql := "SELECT distinct item_id FROM sy_org_dict_acl WHERE dict_id='" + dictId + "' " + "AND ((acl_owner in (@ROLE_CODES@) AND acl_otype=1) OR (acl_owner in (@DEPT_CODES@) AND acl_otype=2) OR (acl_owner='@USER_CODE@' AND acl_otype=3))"
		// 替换系统变量
		sql = strings.ReplaceAll(sql, "@ROLE_CODES@", userBean.GetRoleCodeQuotaStr())
		sql = strings.ReplaceAll(sql, "@DEPT_CODES@", userBean.GetDeptCodeQuotaStr())
		sql = strings.ReplaceAll(sql, "@USER_CODE@", userCode)
		log.Info("getDictAcls::sql:{}", sql)
		list, _ := db.Ctx().GetExecutor().Query(sql, nil, nil)
		sb := strutils.NewStringBuilder("")
		for _, acl := range list {
			if !util.IsEmpty(acl.GetStr("ITEM_ID")) {
				sb.Append(acl.GetStr("ITEM_ID")).Append(",")
			}
		}
		if sb.Len() > 0 {
			sb.Truncate(sb.Len() - 1)
		}
		acls = sb.ToString()
		log.Info("getDictAcls::acls:{}", acls)
		cache.CacheMgr.Set(userCode, acls, consts.CACHE_DICT_ACL_PRE_CMPY+dictId)
		return strings.Split(acls, ",")
	}
	return make([]string, 0)
}

func (a *aclMgr) GetDictAcls2(dictId, userCode string) []string {
	items := db.DictMgr.GetItemList(db.DictMgr.GetDict(dictId), db.Ctx().GetCmpy())
	dictAcls := make([]string, 0)
	dictAcls = append(dictAcls, a.GetDictAcls(dictId, userCode)...)
	a.loopMenus(items, dictAcls)
	return dictAcls
}

/**
 * 遍历菜单补权限
 * @param items
 * @param dictAcls
 */
func (a *aclMgr) loopMenus(items []*bean.Bean, dictAcls []string) {

	for _, node := range items {
		if a.nodeChecked(node, dictAcls) && !util.Contains2(dictAcls, node.GetStr("ID")) {
			dictAcls = append(dictAcls, node.GetStr("ID"))
		}
		if node.Contains(consts.CHILD_NODE) {
			a.loopMenus(node.GetBeans(consts.CHILD_NODE), dictAcls)
		}
	}
}

/**
 * 检查叶子是否选中
 * @param node
 * @param dictAcls
 * @return
 */
func (a *aclMgr) nodeChecked(node *bean.Bean, dictAcls []string) bool {
	if node.Contains(consts.CHILD_NODE) {
		child := node.GetBeans(consts.CHILD_NODE)
		for _, item := range child {
			if util.Contains2(dictAcls, item.GetStr("ID")) || (node.Contains(consts.CHILD_NODE) && a.nodeChecked(item, dictAcls)) {
				return true
			}
		}
	}
	return false
}
